package main

import (
	"bytes"
	"fmt"
	"log"
	"math/rand"
	"regexp"
	"strconv"
	"strings"
	"text/template"
	"time"
)


func GenerateData(generateChan chan GenerateMessage,goroutineId uint32, config AppConfig){
	for  {
		args,err := generate(config)
		if err != nil {
			panic(err)
		}
		insertData(generateChan,goroutineId,config,args)
		var duration time.Duration= time.Duration(appConfig.SleepMilliSecond)*time.Millisecond
		time.Sleep(duration)
	}
}
func generate(config AppConfig) ([]interface{},error) {
	rand.Seed(time.Now().UnixNano())
	numb :=rand.Intn(900)+100

	valTypes :=strings.Split(config.InsertValueTypes,",")
	//fmt.Println("\nvalTypes:",valTypes)

	// 创建模板对象, parse关联模板
	tmpl, err := template.New("test").Parse(config.InsertValues)
	if err != nil {
		panic(err)
	}
	// 渲染stu为动态数据, 标准输出到终端
	randomNumber :=numb
	var buffer bytes.Buffer
	err = tmpl.Execute(&buffer, randomNumber)
	if err != nil {
		log.Fatalln("插入值配置有误，err:", err)
		return nil,err
		//panic(err)
	}
	parameters :=strings.Split(buffer.String(),",")
	//fmt.Println("parameters:",parameters)
	if len(valTypes) != len(parameters){
		log.Fatal("插入字段和插入值的数量不一致！~")
		return nil,err
	}

	args := make([]interface{},len(parameters))
	for i := 0; i< len(parameters); i++ {
		valType :=strings.Trim(valTypes[i]," ")
		switch valType {
		case "string":
			args[i]=strings.Trim(parameters[i]," ")
		case "int":
			intVal,err :=strconv.Atoi(parameters[i])
			if err!=nil {
				args[i]=0
			}
			args[i]=intVal
		case "int64":
			int64Val,err :=strconv.ParseInt(parameters[i],10,64)
			if err!=nil {
				args[i]=int64(0)
			}
			args[i]=int64Val
		case "float":
			floatVal,err := strconv.ParseFloat(parameters[i],32)
			if err!=nil {
				args[i]=float32(0)
			}
			args[i]=floatVal
		default:
			args[i]=parameters[i]
		}
	}
	return args,err
}
func insertData(generateChan chan GenerateMessage,goroutineId uint32, config AppConfig,args []interface{}) {

	//解释正则表达式
	reg := regexp.MustCompile(`values(.*)`)
	if reg == nil {
		log.Println("MustCompile err")
		return
	}
	matchs :=reg.FindAllStringSubmatch(config.InsertSql,-1)
	if len(matchs) < 1 || len(matchs[0]) < 2 {
		log.Println("insert-sql config err")
		return
	}
	valSql := matchs[0][1]
	sqlSlie := make([]string,config.BatchCount)
	sqlSlie[0]=config.InsertSql
	for i :=1; i < config.BatchCount ;i++{
		sqlSlie[i]=valSql
	}
	valSqlAll :=strings.Join(sqlSlie,",")

	argsAll := make([]interface{},config.BatchCount* len(args))
	j := 0
	for i:=0; i< len(argsAll); i++ {
		argsAll[i]= args[j]
		j++
		if j >= len(args) {
			j=0
		}
	}
	r, err := Db.Exec(valSqlAll, argsAll...)
	//r, err := Db.Exec(config.InsertSql, "param-"+strconv.Itoa(numb),33)
	if err != nil {
		//fmt.Println("exec failed, ", err)
		log.Println("exec failed, ", err)
		return
	}
	id, err := r.LastInsertId()
	if err != nil {
		fmt.Println("get LastId failed, ", err)
		return
	}

	now :=time.Now()
	generateMessage := GenerateMessage{}
	generateMessage.GoroutineId=goroutineId
	generateMessage.LastId =id
	generateMessage.EndTime = now
	generateChan <- generateMessage
	//fmt.Printf("\r %s total: %d条, useTime: %.2f分钟,succ lastId:%d", time.Now().Format("2006-01-02 15:04:05"), *total, duration.Minutes(), id)
}

func InsertDataEnd()  {
	fmt.Println("\n**********数据生成终止***********")
	ticker :=time.NewTicker(time.Second)
	maxWaitNumber := 5
	for{
		select {
		case <- ticker.C:
			maxWaitNumber--
			fmt.Printf("\r... %v", maxWaitNumber)
		}
		if maxWaitNumber < 0 {
			break
		}
	}
	//time.Sleep(time.Second*2)
}
